package earogya.ehr.medical_records.messages;

import java.io.IOException;
import java.util.Date;

import org.hibernate.HibernateException;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.DataTypeException;
import ca.uhn.hl7v2.model.v251.message.ADT_A01;
import ca.uhn.hl7v2.model.v251.segment.DG1;
import ca.uhn.hl7v2.model.v251.segment.OBX;
import ca.uhn.hl7v2.model.v251.segment.PID;
import ca.uhn.hl7v2.model.v251.segment.PV1;
import earogya.ehr.medical_records.BhtEntry;
import earogya.ehr.medical_records.HibernateManager;

/***
 * This event is used to add new bht entries to the patient's bht
 * @author Chamendri
 *
 */
public class ADT_08_Handler {

	private ADT_A01 adtMsg;
	private HibernateManager hibernate_manager=new HibernateManager();
	
	public ADT_08_Handler(ADT_A01 adtMsg){
		this.adtMsg=adtMsg;
	}
	
	public String manageMessage() throws IOException, HL7Exception{
		String ack=null;
		try{
			int bht_id=this.getBhtId();
			if(bht_id!=-1){
				Boolean isSuccessfulDiagnosis=this.enterDiagnosis(bht_id);
				Boolean isSuccessfulObservation=this.enterObservations(bht_id);
				if(isSuccessfulDiagnosis && isSuccessfulObservation){
					ack=adtMsg.generateACK().encode();
				}
			}
		}catch(HL7Exception e){
			ack=adtMsg.generateACK("AE", e).encode();
		}
		return ack;
	}
	
	/***
	 * Get the bht id for a given admission of a given patient.
	 * @return
	 * @throws HL7Exception 
	 */
	public int getBhtId() throws HL7Exception{
		int bht_id=-1;
		PID pid=adtMsg.getPID();
		int patient_id=Integer.parseInt(pid.getPatientID().getIDNumber().getValue());
		//String admission_date=pv1.getAdmitDateTime().getTime().getValueAsDate().toGMTString();
		Object[][] fieldsAndValues={{"patient_id", patient_id}, {"status", "in"}};
		int admission_id=hibernate_manager.queryValuesFromDatabase(fieldsAndValues, "admission_id", "Admission", "admission");
		if(admission_id!=-1){
			Object[][] fav={{"admission_id", admission_id}};
			bht_id=hibernate_manager.queryValuesFromDatabase(fav,"bht_id" , "Bht", "bht");
		}
		else{
			HL7Exception ex=new HL7Exception("Incorrect patient id");
			throw ex;
		}
		return bht_id;
	}
	
	
	/**
	 * Enter values in the OBX-observation segment to the bht_entry table
	 * @param bht_id
	 * @return isSucessful
	 * @throws NumberFormatException
	 * @throws DataTypeException
	 * @throws HL7Exception
	 */
	private Boolean enterObservations(int bht_id) throws NumberFormatException, DataTypeException, HL7Exception{
		OBX observation=adtMsg.getOBX();
		Boolean isSuccessful=true;
		if(observation.getObservationValue(0).getData().encode()!=null){
			isSuccessful=addBhtEntry(bht_id, "",observation.getObservationValue(0).getData().encode(),observation.getResponsibleObserver(0).getIDNumber().getValue(), observation.getDateTimeOfTheObservation().getTime().getValueAsDate());
		}
		return isSuccessful;
	}
	
	/***
	 * Enter values in the DG1-diagnosis segment to the bht_entry table 
	 * @param bht_id
	 * @throws HL7Exception
	 */
	private Boolean enterDiagnosis(int bht_id) throws HL7Exception{
		DG1 diagnosis=adtMsg.getDG1();
		Boolean isSuccessful=true;
		if(diagnosis.getDiagnosisDescription().getValue()!=null){
			isSuccessful=addBhtEntry(bht_id, diagnosis.getDiagnosisDescription().getValue(),"", diagnosis.getDiagnosingClinician(0).getIDNumber().getValue(), diagnosis.getDiagnosisDateTime().getTime().getValueAsDate());
		}
		return isSuccessful;
	}
	
	/**
	 * Add the values to BhtEntry object and save to the database using hibernate.
	 * @param bht_id
	 * @param description
	 * @param officer_id
	 * @param entrydate
	 * @return isSuccesful
	 */
	private Boolean addBhtEntry(int bht_id, String descriptionDiagnosis, String descriptionObservation, String officer_id, Date entrydate) throws HibernateException, HL7Exception{
		BhtEntry entry=new BhtEntry();
		entry.setBht_id(bht_id);
		entry.setDescription_diagnosis(descriptionDiagnosis);
		entry.setDescription_observation(descriptionObservation);
		entry.setEntered_officer_id(officer_id);
		entry.setEntered_time(entrydate);
		Boolean isSuccesful=hibernate_manager.saveObject(entry);
		return isSuccesful;
	}
}
